﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using Client.model;

namespace Client.ViewModel
{
    public class MainViewModel
    {
        HearingData hearing = new HearingData();
        model.Pitting pitting = new model.Pitting();
        Command command = new Command();
        
        AdditionalFunction additionalFunction = new AdditionalFunction();
        UserManager userManager = new UserManager();
        Table table = new Table();        

        RelayCommand userInfoSave;
        RelayCommand userInfoDelete;
        RelayCommand userAdd;
        RelayCommand hearingSave;
        RelayCommand basic;
        RelayCommand advanced;

        RelayCommand noiseControlOn;
        RelayCommand noiseControlOff;
        RelayCommand feedbackControlOn;
        RelayCommand feedbackControlOff;
        RelayCommand batteryAlarmOn;
        RelayCommand batteryAlarmOff;
        RelayCommand volumeControlOn;
        RelayCommand volumeControlOff;
        RelayCommand crescendo;
        RelayCommand decrescendo;

        RelayCommand overall_Gain_Left_Up;
        RelayCommand overall_Gain_Left_Down;
        RelayCommand loudSound_Gain_Left_Up;
        RelayCommand loudSound_Gain_Left_Down;
        RelayCommand softSound_Gain_Left_Up;
        RelayCommand softSound_Gain_Left_Down;
        RelayCommand overall_Right_GainUp;
        RelayCommand overall_Right_GainDown;
        RelayCommand loudSound_Right_GainUp;
        RelayCommand loudSound_Right_GainDown;
        RelayCommand softSound_Right_GainUp;
        RelayCommand softSound_Right_GainDown;

        RelayCommand mode1_Occlusion_Left_Low;
        RelayCommand mode1_Occlusion_Left_High;
        
        public MainViewModel() {
            //PittingDataSetting();//입력으로부터 
            OnHearingSave();
            MapSetting();

            userInfoSave = new RelayCommand(param => OnUserInfoSave());
            userInfoDelete = new RelayCommand(param => OnUserInfoDelete());
            userAdd = new RelayCommand(param => OnUserAdd());
            hearingSave = new RelayCommand(param => OnHearingSave());
            basic = new RelayCommand(param => OnBasic());
            advanced = new RelayCommand(param => OnAdvanced());

            noiseControlOn = new RelayCommand(param => OnNoiseControlOn());
            noiseControlOff = new RelayCommand(param => OnNoiseControlOff());
            feedbackControlOn = new RelayCommand(param => OnFeedbackControlOn());
            feedbackControlOff = new RelayCommand(param => OnFeedbackControlOff());
            batteryAlarmOn = new RelayCommand(param => OnBatteryAlarmOn());
            batteryAlarmOff = new RelayCommand(param => OnBatteryAlarmOff());
            volumeControlOn = new RelayCommand(param => OnVolumeControlOn());
            volumeControlOff = new RelayCommand(param => OnVolumeControlOff());
            crescendo = new RelayCommand(param => OnCrescendo());
            decrescendo = new RelayCommand(param => OnDecrescendo());

            overall_Gain_Left_Up = new RelayCommand(param => OverallLeftUp());
            overall_Gain_Left_Down = new RelayCommand(param => OverallLeftDown());
            loudSound_Gain_Left_Up = new RelayCommand(param => LoudLeftUp());
            loudSound_Gain_Left_Down = new RelayCommand(param => LoudLeftDown());
            softSound_Gain_Left_Up = new RelayCommand(param => SoftLeftUp());
            softSound_Gain_Left_Down = new RelayCommand(param => SoftLeftDown());
            overall_Right_GainUp = new RelayCommand(param => OverallRightUp());
            overall_Right_GainDown = new RelayCommand(param => OverallRightDown());
            loudSound_Right_GainUp = new RelayCommand(param => LoudRightUp());
            loudSound_Right_GainDown = new RelayCommand(param => LoudRightDown());
            softSound_Right_GainUp = new RelayCommand(param => SoftRightUp());
            softSound_Right_GainDown = new RelayCommand(param => SoftRightDown());

            ShiftGain = new SimpleCommand { ExecuteDelegate = x => OnShiftGain(x) };                        

            mode1_Occlusion_Left_Low= new RelayCommand(param => Mode1_Occlusion_Left(param));
            mode1_Occlusion_Left_High = new RelayCommand(param => Mode1_Occlusion_Right(param));
        }       
       
        internal void Left_Checked(int tableIndex)
        {
            int[] leftMap50 = table.getColumn(tableIndex, 0);
            int[] leftMap90 = table.getColumn(tableIndex, 4);

            pitting.setSideData(leftMap50, false, 0);
            pitting.setSideData(leftMap90, false, 1);
        }

        internal void Right_Checked(int tableIndex)
        {
            int[] rightMap50 = table.getColumn(tableIndex, 0);
            int[] rightMap90 = table.getColumn(tableIndex, 4);

            pitting.setSideData(rightMap50, true,0);
            pitting.setSideData(rightMap90, true, 1);
        }

        public void MapSetting()
        {
            int tableIndex = 0;
            int[] leftMap50 = table.getColumn(tableIndex, 0);
            int[] leftMap90 = table.getColumn(tableIndex, 4);

            pitting.setSideData(leftMap50, false, 0);
            pitting.setSideData(leftMap90, false, 1);

            tableIndex = 1;
            int[] rightMap50 = table.getColumn(tableIndex, 0);
            int[] rightMap90 = table.getColumn(tableIndex, 4);

            pitting.setSideData(rightMap50, true, 0);
            pitting.setSideData(rightMap90, true, 1);
        }

        private void OnBasic()
        {
            pitting.IsBasic = true;
            PittingDataSetting();
        }

        private void OnAdvanced()
        {
            pitting.IsBasic = false;
            PittingDataSetting();
        }

        private void PittingDataSetting()
        {
            int[] rightData = hearing.RightBasic;
            int[] leftData = hearing.LeftBasic;

            if (!pitting.IsBasic)
            {               
                rightData = hearing.RightAdvanced;
                leftData = hearing.LeftAdvanced;
            }

            pitting.setSideData(rightData, false,0);
            pitting.setSideData(leftData, true,0);
            pitting.setSideData(rightData, false, 1);
            pitting.setSideData(leftData, true, 1);
        }

        public void OnHearingSave()
        {
            int[] leftAdd = new int[hearing.LeftBasic.Length+2];
            int[] rightAdd = new int[hearing.RightBasic.Length + 2];

            for (int i = 0; i < hearing.LeftBasic.Length; i++) {
                leftAdd[i+1] = hearing.LeftBasic[i];
                rightAdd[i + 1] = hearing.RightBasic[i];
            }

            leftAdd[0] = hearing.LeftBasic[0];
            leftAdd[leftAdd.Length - 1] = hearing.LeftBasic[hearing.LeftBasic.Length - 1];
            rightAdd[0] = hearing.RightBasic[0];
            rightAdd[leftAdd.Length - 1] = hearing.RightBasic[hearing.RightBasic.Length - 1];

            pitting.setHearingData(leftAdd, rightAdd, 110, 300);
            command.Hearing_Save();
        }  

        internal void UserSelected(object selectedItem)
        {
            userManager.UserSelected(selectedItem);
        }
        private void OnUserAdd()
        {
            userManager.UserAdd();
        }

        private void OnUserInfoSave()
        {
            userManager.SaveUser();
        }

        private void OnUserInfoDelete()
        {
            userManager.DeleteUser();
        }

        public void Mode1_Occlusion_Left(object param)
        {
            int side = 0;
            if (pitting.IsLeftRightSynchronous) side = 2;

            pitting.PointChange(side, true, 0 , (double)param);

            command.Pitting_Mode1_Left_Occlusion_Low();
        }

        public void Mode1_Occlusion_Right(object param)
        {
            int side = 1;
            if (pitting.IsLeftRightSynchronous) side = 2;

            pitting.PointChange(side, true, 0, (double)param);
            command.Pitting_Mode1_Left_Occlusion_High();
        }

        public void OverallLeftUp()
        {
            int side = 0;
            if (pitting.IsLeftRightSynchronous) side = 2;

            pitting.PointChange(side, true, 0);

            command.Pitting_Mode1_Overall_Up();
        }
        
        public void OverallLeftDown()
        {
            int side = 0;
            if (pitting.IsLeftRightSynchronous) side = 2;

            pitting.PointChange(side, false, 0);
            
            command.Pitting_Mode1_Overall_Down();
        }

        public void LoudLeftUp()
        {
            int side = 0;
            if (pitting.IsLeftRightSynchronous) side = 2;

            pitting.PointChange(side, true, 1);

            command.Pitting_Mode1_Loud_Up();
        }

        public void LoudLeftDown()
        {
            int side = 0;
            if (pitting.IsLeftRightSynchronous) side = 2;

            pitting.PointChange(side, false, 1);
            command.Pitting_Mode1_Loud_Down();
        }

        public void SoftLeftUp()
        {
            int side = 0;
            if (pitting.IsLeftRightSynchronous) side = 2;

            pitting.PointChange(side, true, 2);
            command.Pitting_Mode1_Soft_Up();
        }

        public void SoftLeftDown()
        {
            int side = 0;
            if (pitting.IsLeftRightSynchronous) side = 2;

            pitting.PointChange(side, false, 2);
            command.Pitting_Mode1_Soft_Down();
        }

        public void OverallRightDown()
        {
            int side = 1;
            if (pitting.IsLeftRightSynchronous) side = 2;

            pitting.PointChange(side, false, 0);
            command.Pitting_Mode1_Overall_Down();
        }

        public void OverallRightUp()
        {
            int side = 1;
            if (pitting.IsLeftRightSynchronous) side = 2;

            pitting.PointChange(side, true, 0);
            command.Pitting_Mode1_Overall_Up();
        }

        public void LoudRightDown()
        {
            int side = 1;
            if (pitting.IsLeftRightSynchronous) side = 2;

            pitting.PointChange(side, false, 1);
            command.Pitting_Mode1_Loud_Down();
        }

        public void LoudRightUp()
        {
            int side = 1;
            if (pitting.IsLeftRightSynchronous) side = 2;

            pitting.PointChange(side, true, 1);
            command.Pitting_Mode1_Loud_Up();
        }

        public void SoftRightDown()
        {
            int side = 1;
            if (pitting.IsLeftRightSynchronous) side = 2;

            pitting.PointChange(side, false, 2);
            command.Pitting_Mode1_Soft_Down();
        }

        public void SoftRightUp()
        {
            int side = 1;
            if (pitting.IsLeftRightSynchronous) side = 2;

            pitting.PointChange(side, true, 2);
            command.Pitting_Mode1_Soft_Up();
        }

        private void OnShiftGain(object x)
        {
            float param = float.Parse(x.ToString());
            int gain = (int)param;
            int gainAbs = Math.Abs(gain);
            int side = (int)(Math.Abs(param) * 10) % 10;            
            int index = 0;
            if (pitting.IsLeftRightSynchronous) side = 2;

            if (gainAbs <= 250)
            {
                index = 0;
            }
            else if (gainAbs <= 500) { index = 1; command.Pitting_Mode1_Left_0to200hz(); }
            else if (gainAbs <= 750) { index = 2; command.Pitting_Mode1_Left_0to200hz(); }
            else if (gainAbs <= 1000) { index = 3; command.Pitting_Mode1_Left_0to200hz(); }
            else if (gainAbs <= 1500) { index = 4; command.Pitting_Mode1_Left_1500to2250hz(); }
            else if (gainAbs <= 2000) { index = 5; command.Pitting_Mode1_Left_1500to2250hz(); }
            else if (gainAbs <= 2250){ index = 6; command.Pitting_Mode1_Left_2250to4000hz(); }
            else if (gainAbs <= 2750) { index = 7; command.Pitting_Mode1_Left_2250to4000hz(); }
            else if (gainAbs <= 3000) { index = 8; command.Pitting_Mode1_Left_2250to4000hz(); }
            else if (gainAbs <= 3500) { index = 9; command.Pitting_Mode1_Left_2250to4000hz(); }
            else if (gainAbs <= 3750) { index = 10; command.Pitting_Mode1_Left_2250to4000hz(); }
            else if (gainAbs <= 4000) { index = 11; command.Pitting_Mode1_Left_2250to4000hz(); }
            else if (gainAbs <= 4250){ index = 12; command.Pitting_Mode1_Left_2250to4000hz(); }
            else if (gainAbs <= 5000) { index = 13; command.Pitting_Mode1_Left_2250to4000hz(); }
            else if (gainAbs <= 6000) { index = 14; command.Pitting_Mode1_Left_2250to4000hz(); }
            else if (gainAbs <= 8000) { index = 15; command.Pitting_Mode1_Left_2250to4000hz(); }

            pitting.PointChange(side, true, index);
        }

        private void OnCrescendo()
        {
            command.Additional_Crescendo();
        }

        private void OnDecrescendo()
        {
            command.Additional_Decrescendo();
        }

        private void OnVolumeControlOn()
        {
            command.Additional_Volumne_Control_On();
        }

        private void OnVolumeControlOff()
        {
            command.Additional_Volumne_Control_Off();
        }

        private void OnBatteryAlarmOn()
        {
            command.Additional_Battery_Alarm_On();
        }

        private void OnBatteryAlarmOff()
        {
            command.Additional_Battery_Alarm_Off();
        }

        private void OnFeedbackControlOn()
        {
            command.Additional_Feedback_Control_On();   
        }

        private void OnFeedbackControlOff()
        {
            command.Additional_Feedback_Control_Off();   
        }

        private void OnNoiseControlOn()
        {
            command.Additional_Noise_Control_On();   
        }

        private void OnNoiseControlOff()
        {
            command.Additional_Noise_Control_Off();
        }      

        public model.Pitting Pitting
        {
            get { return pitting; }
            set { pitting = value; }
        }

        public HearingData Hearing
        {
            get { return hearing; }
            set { hearing = value; }
        }

        public ICommand Overall_Gain_Left_Up { get { return overall_Gain_Left_Up; }}
        public ICommand Overall_Gain_Left_Down { get { return overall_Gain_Left_Down; } }
        public ICommand LoudSound_Gain_Left_Up {get { return loudSound_Gain_Left_Up; }}
        public ICommand LoudSound_Gain_Left_Down {get { return loudSound_Gain_Left_Down; }}
        public ICommand SoftSound_Gain_Left_Up {get { return softSound_Gain_Left_Up; }}
        public ICommand SoftSound_Gain_Left_Down{get { return softSound_Gain_Left_Down; }}
        public ICommand Overall_Right_GainUp { get { return overall_Right_GainUp; }}
        public ICommand Overall_Right_GainDown {get { return overall_Right_GainDown; } }
        public ICommand LoudSound_Right_GainUp { get { return loudSound_Right_GainUp; }}
        public ICommand LoudSound_Right_GainDown {get { return loudSound_Right_GainDown; }}
        public ICommand SoftSound_Right_GainUp { get { return softSound_Right_GainUp; } }
        public ICommand SoftSound_Right_GainDown { get { return softSound_Right_GainDown; } }    
        public ICommand Mode1_Occlusion_Left_Low      { get { return mode1_Occlusion_Left_Low; } }
        public ICommand Mode1_Occlusion_Left_High     { get { return mode1_Occlusion_Left_High; } }

        public ICommand UserInfoSave { get { return userInfoSave; } }
        public ICommand UserInfoDelete { get { return userInfoDelete; } }        
        public ICommand HearingSave { get { return hearingSave; }}
        public ICommand NoiseControlOn { get { return noiseControlOn; } }      
        public ICommand NoiseControlOff { get { return noiseControlOff; } }      
        public ICommand FeedbackControlOn { get { return feedbackControlOn; } }      
        public ICommand FeedbackControlOff { get { return feedbackControlOff; } }      
        public ICommand BatteryAlarmOn { get { return batteryAlarmOn; } }      
        public ICommand BatteryAlarmOff { get { return batteryAlarmOff; } }              
        public ICommand VolumeControlOn { get { return volumeControlOn; } }              
        public ICommand VolumeControlOff { get { return volumeControlOff; } }              
        public ICommand Crescendo { get { return crescendo; } }              
        public ICommand Decrescendo { get { return decrescendo; } }
        public ICommand UserAdd { get { return userAdd; } }
        public ICommand Basic { get { return basic; } }
        public ICommand Advanced { get { return advanced; } }

        public Command Command { get { return command; } set { command = value; }
        }
        public SimpleCommand ShiftGain { get; private set; }    
        
        public AdditionalFunction AdditionalFunction
        {
            get { return additionalFunction; }
            set { additionalFunction = value; }
        }

        public UserManager UserManager
        {
            get { return userManager; }
            set { userManager = value; }
        }

        public Table Table
        {
            get { return table; }
            set { table = value; }
        }

    }
}
